package com.a2v2.online.store.helper;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;

import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.language.DefaultTemplateLexer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.a2v2.online.store.common.constant.NotificationConstants;
import com.a2v2.online.store.database.dao.contract.INotificationEventDAO;
import com.a2v2.online.store.database.entity.NotificationEvent;
import com.a2v2.online.store.service.constant.EmailProperties;
import com.a2v2.online.store.service.dto.NotificationDTO;
import com.a2v2.online.store.service.dto.NotificationDetailDTO;

@Component
public class NotificationServiceHelper {
 
	private static INotificationEventDAO notificationEventDAO;
	private static EmailProperties emailProperties;
	
	@Autowired
	public void setNotificationEventDAO(INotificationEventDAO notificationEventDAO) {
		NotificationServiceHelper.notificationEventDAO = notificationEventDAO;
	}

	@Autowired
	public void setEmailProperties(EmailProperties emailProperties) {
		NotificationServiceHelper.emailProperties = emailProperties;
	}


	public static boolean isUserAccountLocked(NotificationDTO notificationDTO)
	{
		//TODO: we need to implement the code to check the user account status.
		return false;
	}
	
	public static NotificationDetailDTO getMessageTemplate(NotificationDTO notificationDTO)
	{
		NotificationEvent notificationEvent = notificationEventDAO.findNotificationTemplate(notificationDTO);
		NotificationDetailDTO notificationDetailDTO = new NotificationDetailDTO();
		notificationDetailDTO.setSubjectKey(notificationEvent.getNotificationTemplateDetail().getSubjectKey());
		notificationDetailDTO.setTemplateKey(notificationEvent.getNotificationTemplateDetail().getTemplateKey());
		notificationDetailDTO.setTemplateType(notificationEvent.getNotificationTemplateDetail().getTemplateType());
		return notificationDetailDTO;
	}
	
	public static NotificationDetailDTO loadMessage(NotificationDetailDTO notificationDetailDTO)
	{
		ClassLoader loader = NotificationServiceHelper.class.getClassLoader();
		String template = null;
		InputStream fis = null;
		BufferedInputStream br = null;
		StringBuilder content = new StringBuilder();
		
		if(NotificationConstants.SEND_SMS_NOTIFICATION.equalsIgnoreCase(notificationDetailDTO.getNotificationChannel().getChannel()))
		{
			//TODO: just read the message from ResourceBundle and return.
		}
		
		//TODO: get the EMAIL subject message from Resource bundle and set it to notificationDetailTO.
		if(notificationDetailDTO.getSubjectKey()!=null)
		{
			String resourceBundleName = "com/expresspay/notification/resource/ResourceBundle_"+Locale.getDefault();
			ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName);
			notificationDetailDTO.setSubjectMessage(rb.getString(notificationDetailDTO.getSubjectKey()));
		}
		
		if (notificationDetailDTO.getTemplateKey() != null)
		{
			template =  notificationDetailDTO.getTemplateKey();
			
			//below code is commented to test the new changes
			/*try {
				fis = loader.getResourceAsStream("EmailContent/"+Locale.getDefault()+"/"+template);
				//fis = new FileInputStream("EmailContent/"+Locale.getDefault()+"/"+template);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}*/
			//TODO on behalf of sudip.
			StringTemplateGroup stGroup = new StringTemplateGroup("myGroup","D:/ExpressPay_Itr2/EmailTemplates/EmailContent/en_US",DefaultTemplateLexer.class);/*
			fis = loader.getResourceAsStream("EmailContent/"+Locale.getDefault()+"/"+template);
			Reader reader = new InputStreamReader(fis);*/
			/*StringTemplateGroup stGroup = new StringTemplateGroup(reader);*/
			StringTemplate emailTemplate = null;
			try
			{
				emailTemplate = stGroup.getInstanceOf(template);
			}
			catch(Throwable t)
			{
				t.printStackTrace();
			}
			notificationDetailDTO.setEmailTemplate(emailTemplate);
		}
		//below code is commented to test the new changes
		/*byte b[] = new byte[1024];
		int read = 0;

		if (fis != null)
		{
			br = new BufferedInputStream(fis);
			try {
				while ((read = br.read(b)) > 0)
				{
					content.append(new String(b, 0, read));
				}
			} catch (IOException e) {
				// TODO Need to implement this ....
			}
		}
		else
		{
			//TODO : Log the message as Template is missing.
		}
		notificationDetailDTO.setTemplateMessage(content.toString());*/
		return notificationDetailDTO;
	}
	
	public static MimeMessage constructMailTemplate(NotificationDetailDTO notificationDetailDTO)
	{
		MimeMessage message = null;
		BodyPart bodyPart = null;
		Multipart multiPart = null;
		Properties props = emailProperties.getProperties();
		Session mailSession = Session.getDefaultInstance(props);
		message = new MimeMessage(mailSession);
		notificationDetailDTO = replaceToken(notificationDetailDTO);
		multiPart = new MimeMultipart("related");
		bodyPart = new MimeBodyPart();
		try {
			bodyPart.setContent(notificationDetailDTO.getTemplateMessage(), "text/html; charset=\"UTF-8\"");
			multiPart.addBodyPart(bodyPart);
			if(notificationDetailDTO.getSubjectMessage()!=null){
				message.setSubject(notificationDetailDTO.getSubjectMessage());
			}
			else{
				message.setSubject("<No Subject>");
			}
			message.setContent(multiPart);
			message.setFrom(new InternetAddress(NotificationConstants.EP_SUPPORT_MAIL));
			List<InternetAddress> addressTo = new ArrayList<InternetAddress>();
			for(int i=0; i<notificationDetailDTO.getReceipientMailAddr().size();i++)
			{
				if (!notificationDetailDTO.getReceipientMailAddr().get(i).isEmpty() ) {
					addressTo.add(new InternetAddress(notificationDetailDTO.getReceipientMailAddr().get(i)));
				}
			}
			message.addRecipients(Message.RecipientType.TO, addressTo.toArray(new InternetAddress[addressTo.size()]));
		} catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return message;
	}
	
	private static NotificationDetailDTO replaceToken(NotificationDetailDTO notificationDetailDTO)
	{
		String formattedSubject = null;
		String formattedMessage = null;
		Map subjectParamMap = notificationDetailDTO.getSubjectParamMap();
		if(subjectParamMap!=null)
		{
			formattedSubject = formatMessage(notificationDetailDTO.getSubjectMessage(), subjectParamMap);
			notificationDetailDTO.setSubjectMessage(formattedSubject);
		}
		Map messageParamMap = notificationDetailDTO.getMessageParamMap();
		if(messageParamMap!=null)
		{
			//formattedMessage = formatMessage(notificationDetailDTO.getTemplateMessage(), messageParamMap);
			//notificationDetailDTO.setTemplateMessage(formattedMessage);
			StringTemplate st = notificationDetailDTO.getEmailTemplate();
			st.setAttribute(NotificationConstants.FIRST_NAME, messageParamMap.get(NotificationConstants.FIRST_NAME));
			st.setAttribute(NotificationConstants.LAST_NAME, messageParamMap.get(NotificationConstants.LAST_NAME));
			st.setAttribute("foo",messageParamMap.get(NotificationConstants.TRX_DETAILS));
			st.setAttribute(NotificationConstants.CUST_SUPPORT_EMAIL, messageParamMap.get(NotificationConstants.CUST_SUPPORT_EMAIL));
			st.setAttribute(NotificationConstants.CUST_BANK_NAME, messageParamMap.get(NotificationConstants.CUST_BANK_NAME));
			st.setAttribute(NotificationConstants.MERCHANT_NAME, messageParamMap.get(NotificationConstants.MERCHANT_NAME));
			formattedMessage = st.toString();
			notificationDetailDTO.setTemplateMessage(formattedMessage);
		}
		return notificationDetailDTO;
	}
	
	private static String formatMessage(String message, Map paramMap)
	{
		String resultMsg = null;
		StringTemplate st = new StringTemplate(message);

		Set<String> set = paramMap.keySet();
		Iterator it = set.iterator();

		while (it.hasNext())
		{
			Object obj = it.next();
			st.setAttribute(obj.toString(), paramMap.get(obj));
		}
		resultMsg = st.toString();
		return resultMsg;
	}
}
